home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / ircii2-6.zip / SRC\IRCII-2.6\SOURCE\IRCAUX.C < prev    next >
C/C++ Source or Header  |  1995-01-04  |  26KB  |  1,296 lines

  1. /*
  2.  * ircaux.c: some extra routines... not specific to irc... that I needed 
  3.  *
  4.  * Written By Michael Sandrof
  5.  *
  6.  * Copyright(c) 1990, 1991 
  7.  *
  8.  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
  9.  */
  10.  
  11. #ifndef lint
  12. static    char    rcsid[] = "@(#)$Id: ircaux.c,v 1.25 1994/10/09 06:39:35 mrg Stab $";
  13. #endif
  14.  
  15. #include "irc.h"
  16.  
  17. #if defined(_HPUX_SOURCE) || defined(ESIX) || defined(MIPS_SYSV)
  18. # define _TERMIOS_INCLUDED
  19. # define _INCLUDE_TERMIO
  20. # include <sys/termio.h>
  21. #endif
  22.  
  23. #ifdef HAVE_SYS_UN_H
  24. #include <sys/un.h>
  25. #endif /* HAVE_SYS_UN_H */
  26.  
  27. #ifndef _Windows
  28. #include <pwd.h>
  29. #endif
  30.  
  31. #include "ircaux.h"
  32. #include "output.h"
  33. #include "term.h"
  34.  
  35. extern    struct    in_addr    MyHostAddr;
  36.  
  37. #ifdef    ALLOC_DEBUG
  38. # ifdef  _IBMR2
  39. struct    HeapDesc
  40. {
  41.     u_long     Link;
  42.     u_long     Size;
  43. };
  44. # endif
  45. #define    ALLOC_LIST 2048
  46. static    char    *MemList[ALLOC_LIST];
  47. static    long    MemSize[ALLOC_LIST];
  48. static    int    Init = 0;
  49.  
  50. void    dump_mem()
  51. {
  52.     int    i;
  53.     FILE    *fp;
  54. #ifdef _IBMR2
  55.     struct    HeapDesc *HeapElement;
  56.     char    *lowest;
  57.     char    *highest;
  58.     long    size;
  59. #endif
  60.     int    fits;
  61.  
  62.     fp = fopen("debug.log", "w");
  63.     fprintf(fp, "ircII failed because of a segmentation violation\nKnown allocations follow:\n\n");
  64.     for (i = 0; i < ALLOC_LIST; i++)
  65.         if (MemList[i])
  66.         {
  67. #ifdef _IBMR2
  68.     /*
  69.      * The following determines if the size shown for this element of
  70.      * memory matches the size we have recorded in the allocation list.
  71.      * this is very much machine dependant, and could even vary between
  72.      * SysV and BSD on the same machine.
  73.      */
  74.             size = (0x08 << (*((long *) MemList[i] - 1)));
  75.             if (size - 0x08 >= MemSize[i] && (size >> 1) - 0x08<MemSize[i])
  76.                 fits = 1;
  77.             else
  78.                 fits = 0;
  79. #else
  80.             fits = 1;
  81. #endif
  82.             fprintf(fp, "     %08lx  %08lx  %08lx  %08lx %s\n",
  83.                 MemList[i], MemSize[i],
  84.                 *((long *) MemList[i]-2),
  85.                 *((long *) MemList[i]-1), fits ? "" : "SUSPICIOUS");
  86.         }
  87. #ifdef _IBMR2
  88.     /*
  89.      * Now we'll walk the heap. We do this by finding the lowest and
  90.          * highest elements in our list, and use the HeapDesc structure
  91.      * to find our way around.
  92.      */
  93.     highest = NULL;
  94.     lowest = NULL;
  95.     for (i = 0; i < ALLOC_LIST; i++)
  96.     {
  97.         if (!MemList[i])
  98.             continue;
  99.         if (!lowest)
  100.             lowest = MemList[i];
  101.         if ((u_long) MemList[i] < (u_long) lowest)
  102.             lowest = MemList[i];
  103.         if ((u_long) MemList[i] > (u_long) highest)
  104.             highest = MemList[i];
  105.     }
  106.     fprintf(fp, "\nKnown allocations start at %08x and end at %08x\n",
  107.         lowest, highest);
  108.     fprintf(fp, "\nHeap walks as follows:\n\n");
  109.     for (HeapElement = lowest-0x08; HeapElement<highest;
  110.         HeapElement = (HeapElement->Link == 0xefL || !HeapElement->Link)?
  111.         (HeapElement+(0x01<<HeapElement->Size)):
  112.         ((struct    HeapDesc *) HeapElement->Link))
  113.     {
  114.         fprintf(fp, "    %08x %08x %08x\n",
  115.             HeapElement + 1,
  116.             HeapElement->Link,
  117.             HeapElement->Size);
  118.     }
  119. #endif
  120.     fclose(fp);
  121.     fprintf(stderr, "Segmentation violation. Debug information saved to debug.log\n");
  122.  
  123.     /*
  124.      * If we resume on a segmentation violation, hopefully it repeats the
  125.      * violation and we get both our log and the core dump from the point
  126.      * at which things fail.
  127.      */
  128.     (void) MY_SIGNAL(SIGSEGV, SIG_DFL, 0);
  129.     return;
  130. }
  131. #endif
  132.  
  133. /*
  134.  * new_free:  Why do this?  Why not?  Saves me a bit of trouble here and
  135.  * there 
  136.  */
  137. void    new_free(ptr)
  138. char    **ptr;
  139. {
  140. #ifdef ALLOC_DEBUG
  141.     FILE    *fp;
  142.     int    i;
  143. #endif
  144. #if DO_USER2
  145.     int    oldmask;
  146. #endif /* DO_USER2 */
  147.  
  148.     if (*ptr)
  149.     {
  150. #if DO_USER2
  151.         oldmask = sigblock(sigmask(SIGUSR2));
  152. #endif /* DO_USER2 */
  153. #ifdef FREE_DEBUG
  154.         if (free(*ptr) < 0)
  155.             put_it("*debug* free failed '%s'", ptr);
  156. #else
  157.         free(*ptr);
  158. #endif
  159. #if DO_USER2
  160.         sigblock(oldmask);
  161. #endif /* DO_USER2 */
  162. #ifdef ALLOC_DEBUG
  163.         for (i = 0; i < ALLOC_LIST; i++)
  164.         {
  165.             if (MemList[i] == *ptr)
  166.                 break;
  167.         }
  168.         if (i == ALLOC_LIST)
  169.         {
  170.             fprintf(stderr,
  171.                 "Memory freed that was never allocated\n");
  172.             fp=fopen("debug.log", "w");
  173.             fprintf(fp, "failed by freeing %08x\n", *ptr);
  174.             fprintf(fp, "List is as follows:\n");
  175.             for (i = 0; i < ALLOC_LIST; i++)
  176.                 if (MemList[i])
  177.                     fprintf(fp, "    %08x  %08x\n",
  178.                         MemList[i], MemSize[i]);
  179.             fclose(fp);
  180.             abort();
  181.         }
  182.         MemList[i] = (char *) 0;
  183.         MemSize[i] = 0L;
  184. #endif
  185.         *ptr = (char *) 0;
  186.     }
  187. }
  188.  
  189. #define WAIT_BUFFER 2048
  190. static char * FAR pointers[WAIT_BUFFER] = {0}, **current = pointers;
  191.  
  192. /*
  193.  * wait_new_free: same as new_free() except that free() is postponed.
  194.  */
  195. void    wait_new_free(ptr)
  196. char    **ptr;
  197. {
  198.     if (*current)
  199.         new_free(current);
  200.     *current++ = *ptr;
  201.     if (current >= pointers + WAIT_BUFFER)
  202.         current = pointers;
  203.     *ptr = (char *) 0;
  204. }
  205.  
  206. /*
  207.  * reall_free: really free the data if level == 0
  208.  */
  209. void    really_free(level)
  210. int    level;
  211. {
  212.     if (level != 0)
  213.         return;
  214.     for (current = pointers; current < pointers + WAIT_BUFFER; current++)
  215.         if (*current)
  216.             new_free(current);
  217.     current = pointers;
  218. }
  219.  
  220. void    reset_pointers()
  221. {
  222.     bzero(pointers, sizeof(*pointers) * WAIT_BUFFER);
  223. }
  224.  
  225. char    *new_realloc(ptr, size)
  226. char    *ptr;
  227. int    size;
  228. {
  229.     char    *new_ptr;
  230. #ifdef ALLOC_DEBUG
  231.     int    i;
  232. #endif
  233.  
  234.     if ((new_ptr = (char *) realloc(ptr, size)) == (char *) 0)
  235.     {
  236.         fprintf(stderr, "realloc failed (%d): %s\nIrc Aborted!\n",
  237.             size, strerror(errno));
  238.         exit(1);
  239.     }
  240. #ifdef ALLOC_DEBUG
  241.     for (i = 0;i < ALLOC_LIST; i++)
  242.         if (MemList[i] == ptr)
  243.             break;
  244.     if (i == ALLOC_LIST)
  245.     {
  246.         fprintf(stderr, "Memory freed that was never allocated");
  247.         abort();
  248.     }
  249.     MemList[i] = new_ptr;
  250.     MemSize[i] = size;
  251. #endif
  252.     return (new_ptr);
  253. }
  254.  
  255. char    *new_malloc(size)
  256. int    size;
  257. {
  258.     char    *ptr;
  259.  
  260. #ifdef    ALLOC_DEBUG
  261.     int    i;
  262.  
  263.     if (!Init)
  264.     {
  265.         Init = 1;
  266.         for (i = 0; i < ALLOC_LIST; i++)
  267.         {
  268.             MemList[i] = (void    *) 0;
  269.             MemSize[i] = 0L;
  270.         }
  271.         if (getenv("DEBUG"))
  272.             (void) MY_SIGNAL(SIGSEGV, dump_mem, 0);
  273.     }
  274. #endif
  275.     if ((ptr = (char *) malloc(size)) == (char *) 0)
  276.     {
  277.         static    char    error[] = "Malloc failed: \nIrc Aborted!\n";
  278.  
  279.         write(2, error, strlen(error));
  280.         write(2, strerror(errno), strlen(strerror(errno)));
  281.         term_reset();
  282.         exit(1);
  283.     }
  284. #ifdef ALLOC_DEBUG
  285.     for (i = 0; i < ALLOC_LIST && MemList[i]; i++)
  286.         ;
  287.     if (i == ALLOC_LIST)
  288.     {
  289.         FILE    *fp;
  290.         int    j;
  291.  
  292.         fprintf(stderr,
  293.             "Out of space in memory record. Probable memory leak\n");
  294.         fp = fopen("debug.log", "w");
  295.         for (i = 0; i < ALLOC_LIST; i++)
  296.         {
  297.             fprintf(fp, "    %08lx %08lx \"", MemList[i],
  298.                 MemSize[i]);
  299.             for (j = 0; j < MemSize[i] && j < 45; j++)
  300.             {
  301.                 if (MemList[i][j] < 32 || MemList[i][j] > 127)
  302.                     putc('.', fp);
  303.                 else
  304.                     putc(MemList[i][j], fp);
  305.             }
  306.             fprintf(fp, "\"\n");
  307.         }
  308.         fclose(fp);
  309.         abort();
  310.     }
  311.     MemList[i]=ptr;
  312.     MemSize[i]=size;
  313. #endif
  314.     return (ptr);
  315. }
  316.  
  317. #ifdef ALLOC_DEBUG
  318. void    alloc_cmd(command, args)
  319. char    *command,
  320.         *args;
  321. {
  322.     char    *arg;
  323.     int    f_count = 0,
  324.         f_dump = 0;
  325.     int    i, j;
  326.     int    count;
  327.     long    size;
  328.     FILE    *fp;
  329.  
  330.     while (arg = next_arg(args, &args))
  331.     {
  332.         while (*arg)
  333.         {
  334.             switch(*arg++)
  335.             {
  336.             case 'c':
  337.             case 'C':
  338.                 f_count = 1;
  339.                 break;
  340.             case 'd':
  341.             case 'D':
  342.                 f_dump = 1;
  343.                 break;
  344.             }
  345.         }
  346.     }
  347.     if (f_dump)
  348.         fp = fopen("debug.log", "w");
  349.     else
  350.         fp = NULL;
  351.     for (size = count = i = 0; i < ALLOC_LIST; i++)
  352.     {
  353.         if (fp && MemList[i])
  354.         {
  355.             fprintf(fp, "    %08lx %08lx \"", MemList[i],
  356.                 MemSize[i]);
  357.             for (j = 0; j < MemSize[i] && j < 45; j++)
  358.             {
  359.                 if (MemList[i][j] < 32 || MemList[i][j] > 127)
  360.                     putc('.', fp);
  361.                 else
  362.                     putc(MemList[i][j], fp);
  363.             }
  364.             fprintf(fp, "\"\n");
  365.         }
  366.         if (MemList[i])
  367.         {
  368.             count++;
  369.             size += MemSize[i];
  370.         }
  371.     }
  372.     if (fp)
  373.         fclose(fp);
  374.     if (f_count)
  375.     {
  376.         say("%d blocks allocated out of %d", count, ALLOC_LIST);
  377.         say("%ld bytes allocated, an average of %ld per block",
  378.                 size, size/count);
  379.     }
  380. }
  381. #endif
  382.  
  383. /*
  384.  * malloc_strcpy:  Mallocs enough space for src to be copied in to where
  385.  * ptr points to.
  386.  *
  387.  * Never call this with ptr pointinng to an uninitialised string, as the
  388.  * call to new_free() might crash the client... - phone, jan, 1993.
  389.  */
  390. void    malloc_strcpy(ptr, src)
  391. char    **ptr;
  392. char    *src;
  393. {
  394.     new_free(ptr);
  395.     if (src)
  396.     {
  397.         *ptr = new_malloc(strlen(src) + 1);
  398.         strcpy(*ptr, src);
  399.     }
  400.     else
  401.         *ptr = (char *) 0;
  402. }
  403.  
  404. /* malloc_strcat: Yeah, right */
  405. void    malloc_strcat(ptr, src)
  406. char    **ptr;
  407. char    *src;
  408. {
  409.     char    *new;
  410.  
  411.     if (*ptr)
  412.     {
  413.         new = (char *) new_malloc(strlen(*ptr) + strlen(src) + 1);
  414.         strcpy(new, *ptr);
  415.         strcat(new, src);
  416.         new_free(ptr);
  417.         *ptr = new;
  418.     }
  419.     else
  420.         malloc_strcpy(ptr, src);
  421. }
  422.  
  423. char    *upper(str)
  424. char    *str;
  425. {
  426.     char    *ptr = (char *) 0;
  427.  
  428.     if (str)
  429.     {
  430.         ptr = str;
  431.         for (; *str; str++)
  432.         {
  433.             if (islower(*str))
  434.                 *str = toupper(*str);
  435.         }
  436.     }
  437.     return (ptr);
  438. }
  439.  
  440. /* case insensitive string searching */
  441. char    *
  442. stristr(source, search)
  443.     char    *source,
  444.             *search;
  445. {
  446.         char    *pointer,
  447.                 *booya = (char *) 0,
  448.                 *booya2 = (char *) 0;
  449.         int     x = 0,
  450.                 len = strlen(search);
  451.  
  452.         if (!source || !*source)
  453.                 return empty_string;
  454.         if (!search || !*search)
  455.                 return empty_string;
  456.  
  457.         malloc_strcpy(&booya, source);
  458.         malloc_strcpy(&booya2, search);
  459.         upper(booya);
  460.         upper(booya2);
  461.  
  462.         pointer = booya;
  463.         while (*pointer)
  464.         {
  465.                 if (pointer[x] == booya2[x])
  466.                 {
  467.                         x++;
  468.                         if (x >= len)
  469.                         {
  470.                                 int where = (int)pointer - (int)booya;
  471.                                 new_free(&booya);
  472.                                 new_free(&booya2);
  473.                                 return (&source[where]);
  474.                         }
  475.                 }
  476.                 else
  477.                 {
  478.                         x = 0;
  479.                         pointer++;
  480.                 }
  481.         }
  482.         new_free(&booya2);
  483.         new_free(&booya);
  484.         return (char *) 0;
  485. }
  486. /* case insensitive string searching from the end */
  487. char    *
  488. rstristr(source,search)
  489.     char    *source,
  490.             *search;
  491. {
  492.         char    *pointer,
  493.                 *booya = (char *) 0,
  494.                 *booya2 = (char *) 0;
  495.         int     x = 0,
  496.                 len = strlen(search),
  497.                 slen = strlen(source);
  498.  
  499.         if (!source || !*source)
  500.                 return empty_string;
  501.         if (!search || !*search)
  502.                 return empty_string;
  503.  
  504.         malloc_strcpy(&booya, source);
  505.         malloc_strcpy(&booya2, search);
  506.         upper(booya);
  507.         upper(booya2);
  508.  
  509.         pointer = booya+slen-len;
  510.         while (*pointer)
  511.         {
  512.                 if (pointer[x] == booya2[x])
  513.                 {
  514.                         x++;
  515.                         if (x >= len)
  516.                         {
  517.                                 int where = (int)pointer - (int)booya;
  518.                                 new_free(&booya2);
  519.                                 new_free(&booya);
  520.                                 return (&source[where]);
  521.                         }
  522.                 }
  523.                 else
  524.                 {
  525.                         x = 0;
  526.                         pointer--;
  527.                 }
  528.         }
  529.         new_free(&booya2);
  530.         new_free(&booya);
  531.         return (char *) 0;
  532. }
  533.  
  534. /*
  535.  * Connect_By_Number Performs a connecting to socket 'service' on host
  536.  * 'host'.  Host can be a hostname or ip-address.  If 'host' is null, the
  537.  * local host is assumed.   The parameter full_hostname will, on return,
  538.  * contain the expanded hostname (if possible).  Note that full_hostname is a
  539.  * pointer to a char *, and is allocated by connect_by_numbers() 
  540.  *
  541.  * The following special values for service exist:
  542.  *
  543.  * 0  Create a socket for accepting connections
  544.  *
  545.  * -1 Create a UDP socket
  546.  *
  547.  * -2 Connect to the address passed in place of the hostname parameter
  548.  *
  549.  * Errors: 
  550.  *
  551.  * -1 get service failed 
  552.  *
  553.  * -2 get host failed 
  554.  *
  555.  * -3 socket call failed 
  556.  *
  557.  * -4 connect call failed 
  558.  */
  559. int    connect_by_number(service, host)
  560. int    service;
  561. char    *host;
  562. {
  563.     int    s = -1;
  564.     char    buf[100];
  565.     struct    sockaddr_in server;
  566.     struct    hostent *hp;
  567.  
  568.     if (service == -2)
  569.     {
  570.         server = (*(struct sockaddr_in *) host);
  571.     }
  572.     else if (service > 0)
  573.     {
  574.         if (host == (char *) 0)
  575.         {
  576.             gethostname(buf, sizeof(buf));
  577.             host = buf;
  578.         }
  579.         if ((server.sin_addr.s_addr = inet_addr(host)) == -1)
  580.         {
  581.             if ((hp = gethostbyname(host)) != NULL)
  582.             {
  583.                 bzero((char *) &server, sizeof(server));
  584.                 bcopy(hp->h_addr, (char *) &server.sin_addr,
  585.                     hp->h_length);
  586.                 server.sin_family = hp->h_addrtype;
  587.             }
  588.             else
  589.                 return (-2);
  590.         }
  591.         else
  592.             server.sin_family = AF_INET;
  593.         server.sin_port = (unsigned short) htons(service);
  594.     }
  595.     if (((service == -1) && ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)) ||
  596.         ((service != -1) && ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)))
  597.         return (-3);
  598.     if (service != -1)
  599.         set_socket_options(s);
  600.     if (service <= 0 && service != -2)
  601.     {
  602.         struct    sockaddr_in localaddr;
  603.  
  604.         bzero(&localaddr, sizeof(struct    sockaddr_in));
  605.         localaddr.sin_family = AF_INET;
  606.         if (!service)
  607.             localaddr.sin_addr.s_addr = INADDR_ANY;
  608.         else
  609.             localaddr.sin_addr = MyHostAddr;
  610.         localaddr.sin_port = 0;
  611.         if (bind(s, (struct sockaddr *) &localaddr,
  612.             sizeof(localaddr)) == -1 ||
  613.             (!service && listen(s, 1) == -1))
  614.         {
  615.             close(s);
  616.             return -4;
  617.         }
  618.         service = sizeof(localaddr);
  619.         getsockname(s, (struct    sockaddr *) &localaddr, &service);
  620.         return (s);
  621.     }
  622. #if defined(PRIV_PORT) || defined(PRIV_PORT_ULC)
  623. #ifdef PRIV_PORT_ULC
  624.     seteuid(0);
  625. #endif
  626.     /* attempt to bind to a privileged port */
  627.     if (geteuid() == 0)
  628.     {
  629.         struct    sockaddr_in localaddr;
  630.         int    portnum;
  631.  
  632.         localaddr = server;
  633.         localaddr.sin_addr.s_addr=INADDR_ANY;
  634.         for (portnum = 1023; portnum > 600; portnum--)
  635.         {
  636.             localaddr.sin_port = htons(portnum);
  637.             if (bind(s, (struct sockaddr *) &localaddr,
  638.                     sizeof(localaddr)) != -1)
  639.                 break;
  640.         }
  641.     }
  642. #ifdef PRIV_PORT_ULC
  643.     seteuid(getuid());
  644. #endif
  645. #endif /*PRIV_PORT*/
  646.     if (connect(s, (struct sockaddr *) & server, sizeof(server)) < 0)
  647.     {
  648. #ifdef ESIX
  649.         t_close(s);
  650.         unmark_socket(s);
  651. #endif /* ESIX */
  652. #ifdef _Windows
  653.         closesocket(s);
  654.         unmark_socket(s);
  655. #endif
  656.         close(s);
  657.         return -4;
  658.     }
  659.     return s;
  660. }
  661.  
  662. char    *next_arg(str, new_ptr)
  663. char    *str,
  664.     **new_ptr;
  665. {
  666.     char    *ptr;
  667.  
  668.     if ((ptr = sindex(str, "^ ")) != NULL)
  669.     {
  670.         if ((str = sindex(ptr, " ")) != NULL)
  671.             *str++ = (char) 0;
  672.         else
  673.             str = empty_string;
  674.     }
  675.     else
  676.         str = empty_string;
  677.     if (new_ptr)
  678.         *new_ptr = str;
  679.     return ptr;
  680. }
  681.  
  682. char    *new_next_arg(str, new_ptr)
  683. char    *str,
  684.     **new_ptr;
  685. {
  686.     char    *ptr,
  687.         *start;
  688.  
  689.     if ((ptr = sindex(str, "^ \t")) != NULL)
  690.     {
  691.         if (*ptr == '"')
  692.         {
  693.             start = ++ptr;
  694.             while ((str = sindex(ptr, "\"\\")) != NULL)
  695.             {
  696.                 switch (*str)
  697.                 {
  698.                 case '"':
  699.                     *str++ = '\0';
  700.                     if (*str == ' ')
  701.                         str++;
  702.                     if (new_ptr)
  703.                         *new_ptr = str;
  704.                     return (start);
  705.                 case '\\':
  706.                     if (*(str + 1) == '"')
  707.                         strcpy(str, str + 1);
  708.                     ptr = str + 1;
  709.                 }
  710.             }
  711.             str = empty_string;
  712.         }
  713.         else
  714.         {
  715.             if ((str = sindex(ptr, " \t")) != NULL)
  716.                 *str++ = '\0';
  717.             else
  718.                 str = empty_string;
  719.         }
  720.     }
  721.     else
  722.         str = empty_string;
  723.     if (new_ptr)
  724.         *new_ptr = str;
  725.     return ptr;
  726. }
  727.  
  728. /* my_stricmp: case insensitive version of strcmp */
  729. int
  730. my_stricmp(str1, str2)
  731.     char    *str1,
  732.         *str2;
  733. {
  734.     int    xor;
  735.  
  736.     for (; *str1 || *str2 ; str1++, str2++)
  737.     {
  738.         if (!*str1 || !*str2)
  739.             return (*str1 - *str2);
  740.         if (isalpha(*str1) && isalpha(*str2))
  741.         {
  742.             xor = *str1 ^ *str2;
  743.             if (xor != 32 && xor != 0)
  744.                 return (*str1 - *str2);
  745.         }
  746.         else
  747.         {
  748.             if (*str1 != *str2)
  749.                 return (*str1 - *str2);
  750.         }
  751.     }
  752.     return 0;
  753. }
  754.  
  755. /* my_strnicmp: case insensitive version of strncmp */
  756. int    
  757. my_strnicmp(str1, str2, n)
  758.     char    *str1,
  759.         *str2;
  760.     int    n;
  761. {
  762.     int    i,
  763.         xor;
  764.  
  765.     for (i = 0; i < n; i++, str1++, str2++)
  766.     {
  767.         if (isalpha(*str1) && isalpha(*str2))
  768.         {
  769.             xor = *str1 ^ *str2;
  770.             if (xor != 32 && xor != 0)
  771.                 return (*str1 - *str2);
  772.         }
  773.         else
  774.         {
  775.             if (*str1 != *str2)
  776.                 return (*str1 - *str2);
  777.         }
  778.     }
  779.     return 0;
  780. }
  781.  
  782. /*
  783.  * strmcpy: Well, it's like this, strncpy doesn't append a trailing null if
  784.  * strlen(str) == maxlen.  strmcpy always makes sure there is a trailing null 
  785.  */
  786. void    strmcpy(dest, src, maxlen)
  787. char    *dest,
  788.     *src;
  789. int    maxlen;
  790. {
  791.     strncpy(dest, src, maxlen);
  792.     dest[maxlen] = '\0';
  793. }
  794.  
  795. /*
  796.  * strmcat: like strcat, but truncs the dest string to maxlen (thus the dest
  797.  * should be able to handle maxlen+1 (for the null)) 
  798.  */
  799. void    strmcat(dest, src, maxlen)
  800. char    *dest,
  801.     *src;
  802. int    maxlen;
  803. {
  804.     int    srclen,
  805.     len;
  806.  
  807.     srclen = strlen(src);
  808.     if ((len = strlen(dest) + srclen) > maxlen)
  809.         strncat(dest, src, srclen - (len - maxlen));
  810.     else
  811.         strcat(dest, src);
  812. }
  813.  
  814. /*
  815.  * strmcat_ue: like strcat, but truncs the dest string to maxlen (thus the dest
  816.  * should be able to handle maxlen + 1 (for the null)). Also unescapes
  817.  * backslashes.
  818.  */
  819. void    strmcat_ue(dest, src, maxlen)
  820. char    *dest,
  821.     *src;
  822. int    maxlen;
  823. {
  824.     int    dstlen;
  825.  
  826.     dstlen = strlen(dest);
  827.     dest += dstlen;
  828.     maxlen -= dstlen;
  829.     while (*src && maxlen > 0)
  830.     {
  831.         if (*src == '\\')
  832.         {
  833.             if (index("npr0", src[1]))
  834.                 *dest++ = '\020';
  835.             else if (*(src + 1))
  836.                 *dest++ = *++src;
  837.             else
  838.                 *dest++ = '\\';
  839.         }
  840.         else
  841.             *dest++ = *src;
  842.         src++;
  843.     }
  844.     *dest = '\0';
  845. }
  846.  
  847. /*
  848.  * scanstr: looks for an occurrence of str in source.  If not found, returns
  849.  * 0.  If it is found, returns the position in source (1 being the first
  850.  * position).  Not the best way to handle this, but what the hell 
  851.  */
  852. extern    int
  853. scanstr(source, str)
  854.     char    *str,
  855.         *source;
  856. {
  857.     int    i,
  858.         max,
  859.         len;
  860.  
  861.     len = strlen(str);
  862.     max = strlen(source) - len;
  863.     for (i = 0; i <= max; i++, source++)
  864.     {
  865.         if (!my_strnicmp(source, str, len))
  866.             return (i + 1);
  867.     }
  868.     return (0);
  869. }
  870.  
  871. /* expand_twiddle: expands ~ in pathnames. */
  872. char    *expand_twiddle(str)
  873. char    *str;
  874. {
  875.     define_big_buffer(buffer);
  876.  
  877.     if (*str == '~')
  878.     {
  879.         str++;
  880.         if (*str == '/' || *str == '\0')
  881.         {
  882.             strmcpy(buffer, my_path, BIG_BUFFER_SIZE);
  883.             strmcat(buffer, str, BIG_BUFFER_SIZE);
  884.         }
  885.         else
  886.         {
  887.             char    *rest;
  888. #ifndef _Windows
  889.             struct    passwd *entry;
  890. #endif
  891.  
  892.             if ((rest = index(str, '/')) != NULL)
  893.                 *rest++ = '\0';
  894. #ifdef _Windows
  895.             if (GetPrivateProfileString("Directories", str, "", buffer, BIG_BUFFER_SIZE, "IRCII.INI"))
  896.             {
  897. #else
  898.             if ((entry = getpwnam(str)) != NULL)
  899.             {
  900.                 strmcpy(buffer, entry->pw_dir, BIG_BUFFER_SIZE);
  901. #endif
  902.                 if (rest)
  903.                 {
  904.                     strmcat(buffer, "/", BIG_BUFFER_SIZE);
  905.                     strmcat(buffer, rest, BIG_BUFFER_SIZE);
  906.                 }
  907.             }
  908.             else
  909.             {
  910.                 free_big_buffer(buffer);
  911.                 return (char *) NULL;
  912.             }
  913.         }
  914.     }
  915.     else
  916.         strmcpy(buffer, str, BIG_BUFFER_SIZE);
  917.     str = '\0';
  918.     malloc_strcpy(&str, buffer);
  919.     free_big_buffer(buffer);
  920.     return (str);
  921. }
  922.  
  923. /* islegal: true if c is a legal nickname char anywhere but first char */
  924. #define islegal(c) ((((c) >= 'A') && ((c) <= '}')) || \
  925.             (((c) >= '0') && ((c) <= '9')) || \
  926.              ((c) == '-') || ((c) == '_'))
  927.  
  928. /*
  929.  * check_nickname: checks is a nickname is legal.  If the first character is
  930.  * bad new, null is returned.  If the first character is bad, the string is
  931.  * truncd down to only legal characters and returned 
  932.  *
  933.  * rewritten, with help from do_nick_name() from the server code (2.8.5),
  934.  * phone, april 1993.
  935.  */
  936. char    *check_nickname(nick)
  937. char    *nick;
  938. {
  939.     char    *s;
  940.  
  941.     if (!nick || *nick == '-' || isdigit(*nick))
  942.         return NULL;
  943.  
  944.     for (s = nick; *s && (s - nick) < NICKNAME_LEN; s++)
  945.         if (!islegal(*s) || isspace(*s))
  946.             break;
  947.     *s = '\0';
  948.  
  949.     return *nick ? nick : NULL;
  950. }
  951.  
  952. /*
  953.  * sindex: much like index(), but it looks for a match of any character in
  954.  * the group, and returns that position.  If the first character is a ^, then
  955.  * this will match the first occurence not in that group.
  956.  */
  957. char    *sindex(string, group)
  958. char    *string,
  959. *group;
  960. {
  961.     char    *ptr;
  962.  
  963.     if (!string || !group)
  964.         return (char *) NULL;
  965.     if (*group == '^')
  966.     {
  967.         group++;
  968.         for (; *string; string++)
  969.         {
  970.             for (ptr = group; *ptr; ptr++)
  971.             {
  972.                 if (*ptr == *string)
  973.                     break;
  974.             }
  975.             if (*ptr == '\0')
  976.                 return string;
  977.         }
  978.     }
  979.     else
  980.     {
  981.         for (; *string; string++)
  982.         {
  983.             for (ptr = group; *ptr; ptr++)
  984.             {
  985.                 if (*ptr == *string)
  986.                     return string;
  987.             }
  988.         }
  989.     }
  990.     return (char *) NULL;
  991. }
  992.  
  993. /* is_number: returns true if the given string is a number, false otherwise */
  994. int    is_number(str)
  995. char    *str;
  996. {
  997.     while (*str == ' ')
  998.         str++;
  999.     if (*str == '-')
  1000.         str++;
  1001.     if (*str)
  1002.     {
  1003.         for (; *str; str++)
  1004.         {
  1005.             if (!isdigit((*str)))
  1006.                 return (0);
  1007.         }
  1008.         return 1;
  1009.     }
  1010.     else
  1011.         return 0;
  1012. }
  1013.  
  1014. /* rfgets: exactly like fgets, cept it works backwards through a file!  */
  1015. char    *rfgets(buffer, size, file)
  1016. char    *buffer;
  1017. int    size;
  1018. FILE    *file;
  1019. {
  1020.     char    *ptr;
  1021.     off_t    pos;
  1022.  
  1023.     if (fseek(file, -2L, 1))
  1024.         return NULL;
  1025.     do
  1026.     {
  1027.         switch (fgetc(file))
  1028.         {
  1029.         case EOF:
  1030.             return NULL;
  1031.         case '\n':
  1032.             pos = ftell(file);
  1033.             ptr = fgets(buffer, size, file);
  1034.             fseek(file, pos, 0);
  1035.             return ptr;
  1036.         }
  1037.     }
  1038.     while (fseek(file, -2L, 1) == 0);
  1039.     rewind(file);
  1040.     pos = 0L;
  1041.     ptr = fgets(buffer, size, file);
  1042.     fseek(file, pos, 0);
  1043.     return ptr;
  1044. }
  1045.  
  1046. /*
  1047.  * path_search: given a file called name, this will search each element of
  1048.  * the given path to locate the file.  If found in an element of path, the
  1049.  * full path name of the file is returned in a static string.  If not, null
  1050.  * is returned.  Path is a colon separated list of directories 
  1051.  */
  1052. char    *path_search(name, path)
  1053. char    *name;
  1054. char    *path;
  1055. {
  1056.     static    char    FAR buffer[BIG_BUFFER_SIZE + 1] = "";
  1057.     char    *ptr,
  1058.         *free_path = (char *) 0;
  1059.  
  1060.     malloc_strcpy(&free_path, path);
  1061.     path = free_path;
  1062.     while (path)
  1063.     {
  1064. #ifdef __MSDOS__
  1065.         if ((ptr = index(path, ';')) != NULL)
  1066. #else
  1067.         if ((ptr = index(path, ':')) != NULL)
  1068. #endif
  1069.             *(ptr++) = '\0';
  1070.         strcpy(buffer, empty_string);
  1071.         if (path[0] == '~')
  1072.         {
  1073.             strmcat(buffer, my_path, BIG_BUFFER_SIZE);
  1074.             path++;
  1075.         }
  1076.         strmcat(buffer, path, BIG_BUFFER_SIZE);
  1077.         strmcat(buffer, "/", BIG_BUFFER_SIZE);
  1078.         strmcat(buffer, name, BIG_BUFFER_SIZE);
  1079.         if (access(buffer, F_OK) == 0)
  1080.             break;
  1081.         path = ptr;
  1082.     }
  1083.     new_free(&free_path);
  1084.     return (path) ? buffer : (char *) 0;
  1085. }
  1086.  
  1087. /*
  1088.  * double_quote: Given a str of text, this will quote any character in the
  1089.  * set stuff with the QUOTE_CHAR. It returns a malloced quoted, null
  1090.  * terminated string 
  1091.  */
  1092. char    *double_quote(str, stuff)
  1093. char    *str;
  1094. char    *stuff;
  1095. {
  1096.     define_big_buffer(buffer);
  1097.     char    *ptr = NULL;
  1098.     char    c;
  1099.     int    pos;
  1100.  
  1101.     if (str && stuff)
  1102.     {
  1103.         for (pos = 0; (c = *str); str++)
  1104.         {
  1105.             if (index(stuff, c))
  1106.             {
  1107.                 if (c == '$')
  1108.                     buffer[pos++] = '$';
  1109.                 else
  1110.                     buffer[pos++] = '\\';
  1111.             }
  1112.             buffer[pos++] = c;
  1113.         }
  1114.         buffer[pos] = '\0';
  1115.         malloc_strcpy(&ptr, buffer);
  1116.     }
  1117.     else
  1118.         malloc_strcpy(&ptr, str);
  1119.     free_big_buffer(buffer);
  1120.     return ptr;
  1121. }
  1122.  
  1123. /*
  1124.  * new_stty: given a string of stty commands sets the tty 
  1125.  *           via ioctls TCGETA/TCSETA.
  1126.  *
  1127.  * WARNING: if someone of the architectures specified in 
  1128.  *          #if statement don't work ... please comment out
  1129.  *          the relative statement and send a report to
  1130.  *   
  1131.  *          mez002@cdc835.cdc.polimi.it  or
  1132.  *          rfac@ghost.unimi.it
  1133.  *          
  1134.  *          or talk with me on IRC ... (i think is better)
  1135.  *
  1136.  *                                    - Allanon -
  1137.  *
  1138.  */
  1139. void    new_stty(option)
  1140. char    *option;
  1141. {
  1142. #ifndef _Windows
  1143. #if defined(_HPUX_SOURCE) || defined(ESIX) || defined(MIPS_SYSV)
  1144.     struct    termio ttyset;
  1145.  
  1146.     ioctl(0, TCGETA, &ttyset);
  1147.  
  1148.     if (strstr(option, "opost"))
  1149.     {
  1150.         ttyset.c_oflag |= OPOST;
  1151.     }
  1152.     if (strstr(option, "sane"))
  1153.     {
  1154.         ttyset.c_iflag &= ~(IGNBRK | PARMRK | INPCK | INLCR | IGNCR |
  1155.             IUCLC | IXOFF);
  1156.         ttyset.c_lflag &= ~(XCASE | ECHOE | ECHONL | NOFLSH);
  1157.         ttyset.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL |
  1158.             OFDEL | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
  1159.         ttyset.c_iflag |= (BRKINT | IGNPAR | ISTRIP | ICRNL | IXON);
  1160.         ttyset.c_lflag |= (ISIG | ICANON | ECHO | ECHOK);
  1161.         ttyset.c_oflag |= (OPOST | ONLCR);
  1162.         ttyset.c_cc[VERASE] = CERASE;
  1163.         ttyset.c_cc[VKILL] = CKILL;
  1164.         ttyset.c_cc[VQUIT] = CQUIT;
  1165.         ttyset.c_cc[VINTR] = CINTR;
  1166.         ttyset.c_cc[VEOF] = CEOF;
  1167.         ttyset.c_cc[VEOL] = CNUL;
  1168.         ttyset.c_cc[VSWTCH] = CNUL;
  1169.     }
  1170.     if (strstr(option, "cooked"))   /*  cooked == -raw  */
  1171.     {
  1172.         ttyset.c_cflag &= ~CSIZE;
  1173.         ttyset.c_cflag |= PARENB;
  1174.         ttyset.c_iflag |= (BRKINT | IGNPAR | ISTRIP | IXON);
  1175.         ttyset.c_oflag |= OPOST;
  1176.         ttyset.c_lflag |= (ICANON | ISIG);
  1177.         ttyset.c_cc[VEOF] = CEOF;
  1178.         ttyset.c_cc[VEOL] = CNUL;
  1179.     }
  1180.     if (strstr(option, "raw"))
  1181.     {
  1182.         ttyset.c_cflag &= ~(CSIZE | PARENB);
  1183.         ttyset.c_iflag &= ~(-1);
  1184.         ttyset.c_lflag &= ~(ISIG | ICANON | XCASE);
  1185.         ttyset.c_oflag &= ~OPOST;
  1186.         ttyset.c_cflag |= CS8;
  1187.         ttyset.c_cc[VMIN] = 1;
  1188.         ttyset.c_cc[VTIME] = 1;
  1189.     }
  1190.     if (strstr(option, "-echo"))
  1191.         ttyset.c_lflag &= ~ECHO;
  1192.  
  1193.     ioctl(0, TCSETAW, &ttyset);
  1194. #else
  1195.     char    command[256];
  1196.     sprintf(command, "stty %s", option);
  1197.     system(command);               /* IT WILL BE REMOVED IF ALL ARCHIES WORKS */
  1198. #endif
  1199. #endif _Windows
  1200. }
  1201.  
  1202. #ifdef ZCAT
  1203. /* Here another interesting stuff:
  1204.  * it handle zcat of compressed files
  1205.  * You can manage compressed files in this way:
  1206.  *
  1207.  * IN: char *name, the compressed file FILENAME
  1208.  * OUT: a FILE *, from which read the expanded file
  1209.  *
  1210.  */
  1211. FILE    *zcat(name)
  1212. char    *name;
  1213. {
  1214.     FILE    *fp;
  1215.     int    in[2];
  1216.  
  1217.     in[0] = -1;
  1218.     in[1] = -1;
  1219.     if (pipe(in))
  1220.     {
  1221.         say("Unable to start decompression process: %s", strerror(errno));
  1222.         if(in[0] != -1)
  1223.         {
  1224.             close(in[0]);
  1225.             close(in[1]);
  1226.         }
  1227.         return(NULL);
  1228.     }
  1229.     switch(fork())
  1230.     {
  1231.     case -1:
  1232.         say("Unable to start decompression process: %s", strerror(errno));
  1233.         return(NULL);
  1234.     case 0:
  1235.         (void) MY_SIGNAL(SIGINT, SIG_IGN, 0);
  1236.         dup2(in[1], 1);
  1237.         close(in[0]);
  1238.         setuid(getuid());
  1239.         setgid(getgid());
  1240.         execl(ZCAT, ZCAT, name, NULL);
  1241.         exit(0);
  1242.     default:
  1243.         close(in[1]);
  1244.         if ((fp = fdopen(in[0], "r")) == (FILE *) 0)
  1245.         {
  1246.             say("Cannot open pipe file descriptor: %s", strerror(errno));
  1247.             return(NULL);
  1248.         }
  1249.         break;
  1250.     }
  1251.     return(fp);
  1252. }
  1253. #endif /*ZCAT*/
  1254.  
  1255. #ifdef NEED_INDEX
  1256.  
  1257. extern    char    *index(s, c)
  1258.     char    *s;
  1259.     char    c;
  1260. {
  1261. # ifdef HAVE_STRSTR
  1262.     return strstr(s, c);
  1263. # else
  1264.     
  1265.     int    len = strlen(s);
  1266.  
  1267.     for (; len > 0 && c != *s; s++, len--)
  1268.         ;
  1269.     return (len) ? s : (char *) NULL;
  1270. # endif /* HAVE_STRSTD */
  1271. }
  1272.  
  1273. #endif /* NEED_INDEX */
  1274.  
  1275. #ifdef NEED_RINDEX
  1276.  
  1277. extern    char    *rindex(s, c)
  1278.     char    *s;
  1279.     char    c;
  1280. {
  1281. # ifdef HAVE_STRRSTR
  1282.     return strrstr(s, c);
  1283. # else
  1284.  
  1285.     int    len = strlen(s);
  1286.     char    *t = s;
  1287.  
  1288.     s += len;
  1289.     for (; s >= t && c != *s; s--)
  1290.         ;
  1291.     return (s < t) ? (char *) NULL : s;
  1292. # endif /* HAVE_STRRSTR */
  1293. }
  1294.  
  1295. #endif /* NEED_RINDEX */
  1296.